package cn.edu.sgu.www.mhxysy.service.children_equipment.impl;

import cn.edu.sgu.www.mhxysy.dto.children_equipment.ChildrenEquipmentAttributeDTO;
import cn.edu.sgu.www.mhxysy.entity.children_equipment.ChildrenEquipment;
import cn.edu.sgu.www.mhxysy.entity.children_equipment.ChildrenEquipmentAttribute;
import cn.edu.sgu.www.mhxysy.entity.children_equipment.ChildrenEquipmentCategory;
import cn.edu.sgu.www.mhxysy.entity.children_equipment.ChildrenEquipmentViewAttribute;
import cn.edu.sgu.www.mhxysy.entity.except.Property;
import cn.edu.sgu.www.mhxysy.enums.PropertyTypes;
import cn.edu.sgu.www.mhxysy.exception.GlobalException;
import cn.edu.sgu.www.mhxysy.mapper.children_equipment.ChildrenEquipmentAttributeMapper;
import cn.edu.sgu.www.mhxysy.mapper.children_equipment.ChildrenEquipmentCategoryMapper;
import cn.edu.sgu.www.mhxysy.mapper.children_equipment.ChildrenEquipmentMapper;
import cn.edu.sgu.www.mhxysy.mapper.children_equipment.ChildrenEquipmentViewAttributeMapper;
import cn.edu.sgu.www.mhxysy.mapper.except.PropertyMapper;
import cn.edu.sgu.www.mhxysy.restful.ResponseCode;
import cn.edu.sgu.www.mhxysy.service.children_equipment.ChildrenEquipmentAttributeService;
import cn.edu.sgu.www.mhxysy.vo.except.AttributeVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 沐雨橙风ιε
 * @version 1.0
 */
@Service
public class ChildrenEquipmentAttributeServiceImpl implements ChildrenEquipmentAttributeService {

    private final PropertyMapper propertyMapper;
    private final ChildrenEquipmentMapper childrenEquipmentMapper;
    private final ChildrenEquipmentCategoryMapper childrenEquipmentCategoryMapper;
    private final ChildrenEquipmentAttributeMapper childrenEquipmentAttributeMapper;
    private final ChildrenEquipmentViewAttributeMapper childrenEquipmentViewAttributeMapper;

    @Autowired
    public ChildrenEquipmentAttributeServiceImpl(
            PropertyMapper propertyMapper,
            ChildrenEquipmentMapper childrenEquipmentMapper,
            ChildrenEquipmentCategoryMapper childrenEquipmentCategoryMapper,
            ChildrenEquipmentAttributeMapper childrenEquipmentAttributeMapper, 
            ChildrenEquipmentViewAttributeMapper childrenEquipmentViewAttributeMapper) {
        this.propertyMapper = propertyMapper;
        this.childrenEquipmentMapper = childrenEquipmentMapper;
        this.childrenEquipmentCategoryMapper = childrenEquipmentCategoryMapper;
        this.childrenEquipmentAttributeMapper = childrenEquipmentAttributeMapper;
        this.childrenEquipmentViewAttributeMapper = childrenEquipmentViewAttributeMapper;
    }

    @Override
    public void insert(ChildrenEquipmentAttributeDTO childrenEquipmentAttributeDTO) {
        // 验证属性是否重复
        QueryWrapper<ChildrenEquipmentAttribute> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("property_id", childrenEquipmentAttributeDTO.getPropertyId());
        queryWrapper.eq("equipment_id", childrenEquipmentAttributeDTO.getEquipmentId());

        // 通过 宠物装备ID、属性类型ID 查询宠物装备属性
        List<ChildrenEquipmentAttribute> list = childrenEquipmentAttributeMapper.selectList(queryWrapper);

        if (!list.isEmpty()) {
            throw new GlobalException(ResponseCode.CONFLICT, "该装备已经添加了相同的属性，添加失败~");
        }

        if (validateRange(childrenEquipmentAttributeDTO)) {
            ChildrenEquipmentAttribute chongwuEquipmentAttribute = toEntity(childrenEquipmentAttributeDTO);

            Integer propertyId = chongwuEquipmentAttribute.getPropertyId();

            Property property = propertyMapper.selectById(propertyId);

            chongwuEquipmentAttribute.setId(chongwuEquipmentAttribute.uuid());
            chongwuEquipmentAttribute.setType(property.getType());

            childrenEquipmentAttributeMapper.insert(chongwuEquipmentAttribute);
        }
    }

    @Override
    public void deleteById(String id) {
        childrenEquipmentAttributeMapper.deleteById(id);
    }

    @Override
    public void updateById(ChildrenEquipmentAttributeDTO childrenEquipmentAttributeDTO) {
        // 验证属性是否重复
        QueryWrapper<ChildrenEquipmentAttribute> queryWrapper = new QueryWrapper<>();

        queryWrapper.ne(
                childrenEquipmentAttributeDTO.getId() != null,
                "id", childrenEquipmentAttributeDTO.getId()
        );
        queryWrapper.eq("property_id", childrenEquipmentAttributeDTO.getPropertyId());
        queryWrapper.eq("equipment_id", childrenEquipmentAttributeDTO.getEquipmentId());

        List<ChildrenEquipmentAttribute> attributes = childrenEquipmentAttributeMapper.selectList(queryWrapper);

        if (!attributes.isEmpty()) {
            throw new GlobalException(ResponseCode.CONFLICT, "该装备已经添加了相同的属性，添加失败~");
        }

        if (validateRange(childrenEquipmentAttributeDTO)) {
            ChildrenEquipmentAttribute chongwuEquipmentAttribute = toEntity(childrenEquipmentAttributeDTO);

            childrenEquipmentAttributeMapper.updateById(chongwuEquipmentAttribute);
        }
    }

    @Override
    public List<AttributeVO> selectAttributes(String equipmentId) {
        return childrenEquipmentAttributeMapper.selectAttributes(equipmentId);
    }

    @Override
    public List<ChildrenEquipmentAttribute> selectByEquipmentId(String equipmentId) {
        QueryWrapper<ChildrenEquipmentAttribute> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("equipment_id", equipmentId);

        return childrenEquipmentAttributeMapper.selectList(queryWrapper);
    }

    private ChildrenEquipmentAttribute toEntity(ChildrenEquipmentAttributeDTO chongwuEquipmentAttributeDTO) {
        ChildrenEquipmentAttribute chongwuEquipmentAttribute = new ChildrenEquipmentAttribute();

        chongwuEquipmentAttribute.setId(chongwuEquipmentAttributeDTO.getId());
        chongwuEquipmentAttribute.setEquipmentId(chongwuEquipmentAttributeDTO.getEquipmentId());
        chongwuEquipmentAttribute.setPropertyId(chongwuEquipmentAttributeDTO.getPropertyId());
        chongwuEquipmentAttribute.setPropertyValue(chongwuEquipmentAttributeDTO.getPropertyValue());

        return chongwuEquipmentAttribute;
    }
    
    /**
     * 验证属性范围是否合法
     * @param childrenEquipmentAttributeDTO ChildrenEquipmentAttributeDTO
     * @return boolean
     */
    private boolean validateRange(ChildrenEquipmentAttributeDTO childrenEquipmentAttributeDTO) {
        String equipmentId = childrenEquipmentAttributeDTO.getEquipmentId();
        ChildrenEquipment childrenEquipment = childrenEquipmentMapper.selectById(equipmentId);
        ChildrenEquipmentCategory chongwuEquipmentCategory = childrenEquipmentCategoryMapper.selectById(childrenEquipment.getCategoryId());

        QueryWrapper<ChildrenEquipmentViewAttribute> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("equipment_id", chongwuEquipmentCategory.getType());
        queryWrapper.eq("grade", chongwuEquipmentCategory.getGrade());

        List<ChildrenEquipmentViewAttribute> viewAttributes = childrenEquipmentViewAttributeMapper.selectList(queryWrapper);

        if (!viewAttributes.isEmpty()) {
            Map<String, Object> columnMap = new HashMap<>();

            columnMap.put("type", PropertyTypes.FJSX.getValue());

            List<Property> properties = propertyMapper.selectByMap(columnMap);

            // 附加属性跳过验证
            for (Property property : properties) {
                if (property.getId().equals(childrenEquipmentAttributeDTO.getPropertyId())) {
                    return true;
                }
            }

            // 普通属性验证属性类型和范围
            for (ChildrenEquipmentViewAttribute viewAttribute : viewAttributes) {
                if (viewAttribute.getPropertyId().equals(childrenEquipmentAttributeDTO.getPropertyId())) {
                    Integer min = viewAttribute.getMin();
                    Integer max = viewAttribute.getMax();

                    if (childrenEquipmentAttributeDTO.getPropertyValue() > max || childrenEquipmentAttributeDTO.getPropertyValue() < min) {
                        throw new GlobalException(ResponseCode.FORBIDDEN, "装备属性不合法，数值范围为："+ min + "~" + max);
                    }
                }
            }
        }

        return true;
    }

}